﻿using Serilog.Core;
using Serilog.Events;
using Serilog.Formatting.Display;
using Serilog.Formatting;
using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Runtime.Serialization.Formatters.Binary;
using System.Text;
using System.Threading.Tasks;
using NetMQ.Sockets;
using System.Threading;
using NetMQ;

namespace WatchDog
{
    public static class Serilog
    {
        public static LoggingLevelSwitch loggingLevelSwitch = new LoggingLevelSwitch();
        public static SendToClientSink Sink = new SendToClientSink();

        public static ConcurrentQueue<string> SendLogQueue { get; } = new ConcurrentQueue<string>();

        public static ConcurrentQueue<string> ReceiveLogQueue { get; } = new ConcurrentQueue<string>();

        public static void StartSendLog()
        {
            Task.Run(SendLogTask);
        }
        public static void StartReceiveLog()
        {
             Task.Run(ReceiveLogTask);
       
        }

        private static void ReceiveLogTask()
        {

            using var subSocket = new SubscriberSocket();
            subSocket.Options.ReceiveHighWatermark = 1000;
            subSocket.Connect("tcp://localhost:12345");
            subSocket.Subscribe("");

            while (true)
            {
                var message = subSocket.ReceiveFrameString();
                if (ReceiveLogQueue.Count < 100)
                {
                    ReceiveLogQueue.Enqueue(message);
                }
            }
        }

        private static void SendLogTask()
        {
            using var pubSocket = new PublisherSocket();
            pubSocket.Options.SendHighWatermark = 1000;
            pubSocket.Bind("tcp://localhost:12345");
            while (true)
            {
                if (SendLogQueue.TryDequeue(out var log))
                {
                    pubSocket.SendFrame(log);
                }
            }

        }
    }

    /// <summary>
    /// 自定义日志接收器，实现将日志发送到客户端UI中
    /// </summary>
    public class SendToClientSink : ILogEventSink
    {
        readonly ITextFormatter _textFormatter = new MessageTemplateTextFormatter("{Timestamp} [{Level}] {Message}{Exception}");
 
        public void Emit(LogEvent logEvent)
        {
            if (logEvent != null)
            {
                if (Serilog.SendLogQueue.Count < 100)
                {
                    var renderSpace = new StringWriter();
                    _textFormatter.Format(logEvent, renderSpace);
                    Serilog.SendLogQueue.Enqueue(renderSpace.ToString());
                }
            }

        }
    }
}
